home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / BOOTPCMD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-30  |  14.3 KB  |  619 lines

  1. /*************************************************/
  2. /* Center for Information Technology Integration */
  3. /*           The University of Michigan          */
  4. /*                    Ann Arbor                  */
  5. /*                                               */
  6. /* Dedicated to the public domain.               */
  7. /* Send questions to info@citi.umich.edu         */
  8. /*                                               */
  9. /* BOOTP is documented in RFC 951 and RFC 1048   */
  10. /*************************************************/
  11.  
  12.  
  13.  
  14. #include "global.h"
  15. #ifdef BOOTPSERVER
  16. #include "ctype.h"
  17. #include "commands.h"
  18. #include <sys/stat.h>
  19. #ifndef MSDOS
  20. #include <time.h>
  21. #include <stdarg.h>
  22. #endif
  23. #include "bootpd.h"
  24. #include "udp.h"
  25.  
  26. #if !defined(_lint)
  27. static char rcsid[] OPTIONAL = "$Id: bootpcmd.c,v 1.19 1997/07/31 00:44:20 root Exp root $";
  28. #endif
  29.  
  30. #define BP_DEFAULT_TAB "bootptab"
  31. #define BP_DEFAULT_LOG "bootplog"
  32. #define BP_DEFAULT_DIR "bpfiles"
  33. #define BP_DEFAULT_FILE "boot"
  34.  
  35. static const char *bootptab = BP_DEFAULT_TAB;
  36. static FILE *bootfp;        /* bootptab fp */
  37. static long modtime;        /* last modification time of bootptab */
  38.  
  39. static char bootplog[64] = BP_DEFAULT_LOG;
  40. static int LogInFile = 0;    /* Should bp_log log in a file? */
  41. static int LogOnScreen = 0;    /* Should bp_log log on screen? */
  42.  
  43. static char *line;        /* line buffer for reading bootptab */
  44.  
  45. extern int Nhosts;        /* number of hosts in host structure */
  46. extern struct host hosts[MHOSTS + 1];
  47.  
  48. extern char homedir[64];    /* bootfile homedirectory */
  49. extern char defaultboot[64];    /* default file to boot */
  50. extern uint32 bp_DefaultDomainNS[BP_MAXDNS];    /* default domain name server */
  51. extern struct udp_cb *Bootpd_cb;
  52.  
  53.  
  54. static void readtab_shut (void);
  55. static int bp_Homedir (int argc, char *argv[], void *p);
  56. static int bp_DefaultFile (int argc, char *argv[], void *p);
  57. static int bp_DynamicRange (int argc, char *argv[], void *p);
  58. static int bp_donothing (int argc, char *argv[], void *p);
  59. static int bp_Host (int argc, char *argv[], void *p);
  60. static int bp_rmHost (int argc, char *argv[], void *p);
  61. static int bp_DomainNS (int argc, char *argv[], void *p);
  62. static int bp_Start (int argc, char *argv[], void *p);
  63. static int bp_Stop (int argc, char *argv[], void *p);
  64. static int bp_logFile (int argc, char *argv[], void *p);
  65. static int bp_logScreen (int argc, char *argv[], void *p);
  66. static void dumphosts (void);
  67.  
  68.  
  69. void bootpd (struct iface * iface, struct udp_cb * sock, int16 cnt);
  70.  
  71. static struct cmds BootpdCmds[] =
  72. {
  73.     { "",        bp_donothing,        0, 0, NULLCHAR },
  74.     { "start",    bp_Start,        0, 0, NULLCHAR },
  75.     { "stop",    bp_Stop,        0, 0, NULLCHAR },
  76.     { "dns",    bp_DomainNS,        0, 0, NULLCHAR },
  77.     { "dynip",    bp_DynamicRange,    0, 0, NULLCHAR },
  78.     { "host",    bp_Host,        0, 0, NULLCHAR },
  79.     { "rmhost",    bp_rmHost,        0, 0, NULLCHAR },
  80.     { "homedir",    bp_Homedir,        0, 0, NULLCHAR },
  81.     { "defaultfile",bp_DefaultFile,        0, 0, NULLCHAR },
  82.     { "logfile",    bp_logFile,        0, 0, NULLCHAR },
  83.     { "logscreen",    bp_logScreen,        0, 0, NULLCHAR },
  84.     { NULLCHAR,    NULLFP ((int, char **, void *)),
  85.                         0, 0, NULLCHAR }
  86. };
  87.  
  88.  
  89.  
  90. int
  91. bootpdcmd (int argc, char **argv, void *p)
  92. {
  93.     return subcmd (BootpdCmds, argc, argv, p);
  94. }
  95.  
  96.  
  97.  
  98. /* Start up bootp service */
  99. static int
  100. bp_Start (int argc, char *argv[] OPTIONAL, void *p OPTIONAL)
  101. {
  102. struct socket lsock;
  103. time_t tloc;
  104. const char *usage = "bootpd start\n";
  105.  
  106.     if (argc != 1) {
  107.         tputs (usage);
  108.         return (-1);
  109.     }
  110.     (void) time (&tloc);
  111.     bp_log ("\n\n####BOOTP server starting at %s\n", ctime (&tloc));
  112.  
  113.     lsock.address = INADDR_ANY;
  114.     lsock.port = IPPORT_BOOTPS;
  115.  
  116.     /* This way is better than recvfrom because it passes the iface in bootpd call */
  117.     /* Listen doesn't work for datagrams. */
  118.  
  119.     if (Bootpd_cb == NULLUDP) {
  120.         if ((Bootpd_cb = open_udp (&lsock, bootpd)) == NULLUDP) {
  121.             tputs ("bootpd: can't open_udp\n");
  122.             return (-1);
  123.         }
  124.     }
  125.     /*
  126.      * Read the bootptab file once immediately upon startup.
  127.      */
  128.  
  129.     (void) da_init ();
  130.     (void) readtab ();
  131.     return (0);
  132. }
  133.  
  134.  
  135.  
  136. /* Stop bootp service */
  137. static int
  138. bp_Stop (int argc, char *argv[] OPTIONAL, void *p OPTIONAL)
  139. {
  140. time_t now;
  141. const char *usage = "bootpd stop\n";
  142.  
  143.     if (argc != 1) {
  144.         tputs (usage);
  145.         return -1;
  146.     }
  147.     (void) time (&now);
  148.  
  149.     Nhosts = 0;
  150.     da_shut ();
  151.     readtab_shut ();
  152.     (void) del_udp (Bootpd_cb);
  153.     Bootpd_cb = NULLUDP;
  154.  
  155.     bp_log ("Bootpd shutdown %s", ctime (&now));
  156.     return (0);
  157. }
  158.  
  159.  
  160.  
  161. static int
  162. bp_logFile (int argc, char *argv[], void *p OPTIONAL)
  163. {
  164. int i;
  165. time_t now;
  166. const char *usage = "bootpd logfile [<file_name> | default] [on | off] \n";
  167.  
  168.     (void) time (&now);
  169.  
  170.     if (argc == 1)
  171.         tprintf ("Bootpd logging to file '%s' turned o%s.\n", bootplog, (LogInFile) ? "n" : "ff");
  172.     else {
  173.         for (i = 1; i < argc; i++) {
  174.             if (strcmp ("?", argv[i]) == 0)
  175.                 tputs (usage);
  176.             else if (strcmp ("off", argv[i]) == 0) {
  177.                 bp_log ("Stopping file logging at %s", ctime (&now));
  178.                 LogInFile = 0;
  179.             } else if (strcmp ("on", argv[i]) == 0) {
  180.                 LogInFile = 1;
  181.                 bp_log ("Starting file logging at %s", ctime (&now));
  182.             } else if (strcmp ("default", argv[i]) == 0) {
  183.                 strcpy (bootplog, BP_DEFAULT_LOG);
  184.                 bp_log ("File for logging set to %s\n", bootplog);
  185.             } else {
  186.                 strcpy (bootplog, argv[1]);
  187.                 bp_log ("File for logging set to %s\n", bootplog);
  188.             }
  189.         }
  190.     }
  191.     return 0;
  192. }
  193.  
  194.  
  195.  
  196. static int
  197. bp_logScreen (int argc, char *argv[], void *p OPTIONAL)
  198. {
  199. const char *usage = "bootpd logscreen [on | off]\n";
  200.  
  201.     if (argc == 1)
  202.         tprintf ("Bootpd logging on screen turned o%s.\n", (LogOnScreen) ? "n" : "ff");
  203.  
  204.     else if (argc == 2) {
  205.         if (strcmp ("on", argv[1]) == 0)
  206.             LogOnScreen = 1;
  207.         else if (strcmp ("off", argv[1]) == 0)
  208.             LogOnScreen = 0;
  209.         else
  210.             tputs (usage);
  211.     } else
  212.         tputs (usage);
  213.     return 0;
  214. }
  215.  
  216.  
  217.  
  218.  
  219. static int
  220. bp_DomainNS (int argc, char *argv[], void *p OPTIONAL)
  221. {
  222. int a0, a1, a2, a3;
  223. int i;
  224. const char *usage = "bootpd dns [<IP addr of domain name server>...]\n";
  225.  
  226.     if (argc == 1) {
  227.         tputs ("Bootp domain name servers: ");
  228.         for (i = 0; (i < BP_MAXDNS) && (bp_DefaultDomainNS[i] != 0); i++)
  229.             tprintf (" %s", inet_ntoa (bp_DefaultDomainNS[i]));
  230.         tputc ('\n');
  231.         return (0);
  232.     }
  233.     if (argc > 1) {
  234.         if ((argc == 2) && (strcmp ("?", argv[1]) == 0)) {
  235.             tputs (usage);
  236.             return 0;
  237.         }
  238.         /* A list of name servers has been given */
  239.         /* reset the domain name server list */
  240.         for (i = 0; i < BP_MAXDNS; i++)
  241.             bp_DefaultDomainNS[i] = 0;
  242.  
  243.         /* get ip address */
  244.         for (i = 1; (i < argc) && (i < BP_MAXDNS); i++) {
  245.             if (4 != sscanf (argv[i], "%d.%d.%d.%d", &a0, &a1, &a2, &a3)) {
  246.                 tprintf ("bad internet address: %s\n", argv[1]);
  247.                 return -1;
  248.             }
  249.             bp_DefaultDomainNS[i - 1] = aton (argv[i]);
  250.         }
  251.     }
  252.     /* record for the loggers sake */
  253.     bp_log ("Bootp domain name servers: ");
  254.     for (i = 0; (i < BP_MAXDNS) && (bp_DefaultDomainNS[i] != 0); i++)
  255.         bp_log (" %s", inet_ntoa (bp_DefaultDomainNS[i]));
  256.     bp_log ("\n");
  257.     return 0;
  258. }
  259.  
  260.  
  261.  
  262. static int
  263. bp_rmHost (int argc, char *argv[], void *p OPTIONAL)
  264. {
  265. int i;
  266. struct host *hp = NULLHOST;
  267. struct host *cp = NULLHOST;
  268. const char *usage = "bootpd rmhost <host name>\n";
  269.  
  270.  
  271.     if (argc == 2) {
  272.         /* Find the host record */
  273.         for (i = 0; i < Nhosts; i++) {
  274.             if (strcmp (hosts[i].name, argv[1]) == 0) {
  275.                 hp = &(hosts[i]);
  276.                 break;
  277.             }
  278.         }
  279.         /* Return if not found */
  280.         if (hp == NULLHOST) {
  281.             tprintf ("Host %s not in host tables.\n", argv[1]);
  282.             return -1;
  283.         }
  284.         bp_log ("Host %s removed from host table\n", hp->name);
  285.         cp = &(hosts[Nhosts - 1]);
  286.         if (hp < cp)
  287.             memcpy ((char *) hp, (char *) cp, sizeof (struct host));
  288.  
  289.         Nhosts--;
  290.         return 0;
  291.     } else
  292.         tputs (usage);
  293.     return 0;
  294. }
  295.  
  296.  
  297.  
  298. /*
  299.  * Printout the hosts table.
  300. */
  301. static void
  302. dumphosts ()
  303. {
  304. int i;
  305. struct host *hp;
  306. struct arp_type *at;
  307.  
  308.     tputs ("\n\nStatus of host table\n");
  309.  
  310.     if (Nhosts == 0) {
  311.         tputs ("     No hosts in host table\n");
  312.         return;
  313.     }
  314.     for (i = 0; i <= Nhosts - 1; i++) {
  315.         hp = &hosts[i];
  316.         at = &Arp_type[hp->htype];
  317.  
  318.         tprintf ("%s  %s  %s  %s  '%s'\n",
  319.              hp->name, ArpNames[hp->htype], (*at->format) (bp_ascii, hp->haddr),
  320.              inet_ntoa (hp->iaddr.s_addr),
  321.              hp->bootfile);
  322.     }
  323. }
  324.  
  325.  
  326.  
  327. static int
  328. bp_Host (int argc, char *argv[], void *p OPTIONAL)
  329. {
  330. struct host *hp;
  331. int a0, a1, a2, a3;
  332. struct arp_type *at;
  333. const char *usage = "bootpd host [<hostname> <hardware type> <hardware addr> <ip addr> [boot file]]\n";
  334.  
  335.     switch (argc) {
  336.         case 1:
  337.             dumphosts ();
  338.             break;
  339.         case 5:
  340.         case 6:
  341.  
  342.             hp = &hosts[Nhosts];
  343.  
  344.             /* get host name */
  345.             strncpy (hp->name, argv[1], sizeof (hp->name));
  346.  
  347.             /* get hardware type */
  348.             /* This code borrowed from Phil Karn's arpcmd.c */
  349.             /* This is a kludge. It really ought to be table driven */
  350.             switch (tolower (argv[2][0])) {
  351.                 case 'n':    /* Net/Rom pseudo-type */
  352.                     hp->htype = ARP_NETROM;
  353.                     break;
  354.                 case 'e':    /* "ether" */
  355.                     hp->htype = ARP_ETHER;
  356.                     break;
  357.                 case 'a':    /* "ax25" */
  358.                     hp->htype = ARP_AX25;
  359.                     break;
  360.                 case 'm':    /* "mac appletalk" */
  361.                     hp->htype = ARP_APPLETALK;
  362.                     break;
  363.                 default:
  364.                     tprintf ("unknown hardware type \"%s\"\n", argv[2]);
  365.                     return -1;
  366.             }
  367.  
  368.             at = &Arp_type[hp->htype];
  369.             if (at->scan == NULLFP ((char *, const char *)))
  370.                 return 1;
  371.  
  372.             /* Destination address */
  373.             (void) (*at->scan) (hp->haddr, argv[3]);
  374.  
  375.  
  376.             /* get ip address */
  377.             if (4 != sscanf (argv[4], "%d.%d.%d.%d", &a0, &a1, &a2, &a3)) {
  378.                 tprintf ("bad internet address: %s\n", argv[1]);
  379.                 return (0);
  380.             }
  381.             hp->iaddr.s_addr = aton (argv[4]);
  382.  
  383.             /* get the bootpfile */
  384.             if (argc == 6)
  385.                 strncpy (hp->bootfile, argv[5], sizeof (hp->bootfile));
  386.             else
  387.                 hp->bootfile[0] = 0;
  388.  
  389.             bp_log ("Host added: %s  %s  %s  %s  '%s'\n",
  390.                 hp->name, ArpNames[hp->htype], (*at->format) (bp_ascii, hp->haddr),
  391.                 inet_ntoa (hp->iaddr.s_addr),
  392.                 hp->bootfile);
  393.  
  394.  
  395.             Nhosts++;
  396.             break;
  397.  
  398.         default:
  399.             tputs (usage);
  400.             break;
  401.     }
  402.     return 0;
  403. }
  404.  
  405.  
  406.  
  407. static int
  408. bp_Homedir (int argc, char *argv[], void *p OPTIONAL)
  409. {
  410. const char *usage = "bootpd homedir [<name of home directory> | default]\n";
  411.  
  412.     if (argc == 1)
  413.         tprintf ("Bootp home directory: '%s'\n", homedir);
  414.     else if (argc == 2) {
  415.         if (strcmp (argv[1], "?") == 0)
  416.             tputs (usage);
  417.         else if (strcmp (argv[1], "default") == 0) {
  418.             strcpy (homedir, BP_DEFAULT_DIR);
  419.             bp_log ("Bootp home directory set to: '%s'\n", homedir);
  420.         } else {
  421.             strcpy (homedir, argv[1]);
  422.             bp_log ("Bootp home directory set to: '%s'\n", homedir);
  423.         }
  424.     } else
  425.         tputs (usage);
  426.     return (0);
  427. }
  428.  
  429.  
  430.  
  431. static int
  432. bp_DefaultFile (int argc, char *argv[], void *p OPTIONAL)
  433. {
  434. const char *usage = "bootpd defaultfile [<name of default boot file> | default]\n";
  435.  
  436.     if (argc == 1)
  437.         tprintf ("Bootp default boot file:  '%s'\n", defaultboot);
  438.     else if (argc == 2) {
  439.         if (strcmp (argv[1], "?") == 0)
  440.             tputs (usage);
  441.         else if (strcmp (argv[1], "default") == 0)
  442.             strcpy (defaultboot, BP_DEFAULT_FILE);
  443.         else {
  444.             strcpy (defaultboot, argv[1]);
  445.             bp_log ("Bootp default boot file set to:  '%s'\n", defaultboot);
  446.         }
  447.     } else
  448.         tputs (usage);
  449.  
  450.     return (0);
  451. }
  452.  
  453.  
  454.  
  455. static int
  456. bp_DynamicRange (int argc, char *argv[], void *p OPTIONAL)
  457. {
  458. int i0, i1, i2, i3;
  459. int32 start, end;
  460. struct iface *iface;
  461. const char *usage = "bootpd dynip [<net name> | <netname>  <IP address> <IP address> | <netname> off]\n";
  462.  
  463.     if (argc == 1) {
  464.         da_status (NULLIF);
  465.         return 0;
  466.     }
  467.     if ((argc == 2) && (strcmp ("?", argv[1]) == 0)) {
  468.         tputs (usage);
  469.         return 0;
  470.     }
  471.     /* get the interface */
  472.     iface = if_lookup (argv[1]);
  473.     if (iface == NULLIF) {
  474.         tprintf ("network '%s' not found\n", argv[1]);
  475.         return (-1);
  476.     }
  477.     if (argc == 2) {
  478.         da_status (iface);
  479.         return 0;
  480.     }
  481.     if (argc == 3) {
  482.         if (strcmp ("off", argv[2]) == 0)
  483.             (void) da_done_net (iface);
  484.         else
  485.             tputs (usage);
  486.     } else if (argc == 4) {
  487.  
  488.         /* get ip address */
  489.         /* check the ip address - isaddr isn't a ka9q function */
  490.         if ((4 != sscanf (argv[2], "%d.%d.%d.%d", &i0, &i1, &i2, &i3)) ||
  491.             (i0 > 255) || (i1 > 255) || (i2 > 255) || (i3 > 255)
  492.             ) {
  493.             tprintf ("bad internet address: %s\n", argv[2]);
  494.             return (-1);
  495.         }
  496.         if ((4 != sscanf (argv[3], "%d.%d.%d.%d", &i0, &i1, &i2, &i3)) ||
  497.             (i0 > 255) || (i1 > 255) || (i2 > 255) || (i3 > 255)
  498.             ) {
  499.             tprintf ("bad internet address: %s\n", argv[3]);
  500.             return (-1);
  501.         }
  502.         start = (long) aton (argv[2]);
  503.         end = (long) aton (argv[3]);
  504.  
  505.         (void) da_serve_net (iface, (uint32) start, (uint32)end);
  506.  
  507.     } else {
  508.         tputs (usage);
  509.         return (0);
  510.     }
  511.  
  512.     return (0);
  513. }
  514.  
  515.  
  516.  
  517. static int
  518. bp_donothing (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  519. {
  520.     return (0);
  521. }
  522.  
  523.  
  524.  
  525. /*
  526.  * Read bootptab database file.  Avoid rereading the file if the
  527.  * write date hasn't changed since the last time we read it.
  528.  */
  529. int
  530. readtab ()
  531. {
  532. struct stat st;
  533.  
  534.     /* If the file hasn't been opened, open it. */
  535.     if (bootfp == 0) {
  536.         if ((bootfp = fopen (bootptab, "r")) == NULLFILE) {
  537.             bp_log ("Can't open bootptab file: %s\n", bootptab);
  538.             return (-1);
  539.         }
  540.     }
  541.     /* Only reread if modified */
  542. #ifdef MSDOS
  543.     (void) stat ((char *) bootptab, &st);
  544. #else
  545.     (void) stat (bootptab, &st);
  546. #endif
  547.     if (st.st_mtime == modtime && st.st_nlink)
  548.         return (0);    /* hasnt been modified or deleted yet */
  549.  
  550.     /* It's been changed, reread. */
  551.  
  552.     if ((bootfp = fopen (bootptab, "r")) == NULLFILE) {
  553.         bp_log ("Can't open %s\n", bootptab);
  554.         return (-1);
  555.     }
  556.     (void) fstat (fileno (bootfp), &st);
  557.     bp_log ("(re)reading %s\n", bootptab);
  558.     modtime = (long) st.st_mtime;
  559.  
  560.     /*
  561.      * read and parse each line in the file.
  562.      */
  563.  
  564.     line = mallocw (BUFSIZ);
  565.  
  566.     while (fgets (line, BUFSIZ, bootfp) != NULLCHAR) {
  567.         if ((line[0] == 0) || (line[0] == '#') || (line[0] == ' '))
  568.             continue;
  569.  
  570.         if (cmdparse (BootpdCmds, line, NULL) == -1)
  571.             continue;
  572.  
  573.     }
  574.     (void) fclose (bootfp);
  575.     free (line);
  576.     return (0);
  577. }
  578.  
  579.  
  580.  
  581. static void
  582. readtab_shut ()
  583. {
  584.     modtime = 0;
  585. }
  586.  
  587.  
  588.  
  589. /*
  590.  * log an error message
  591.  *
  592.  */
  593. void
  594. bp_log (const char *fmt,...)
  595. {
  596. FILE *fp;
  597. va_list ap;
  598.  
  599.     if (LogOnScreen) {
  600.         va_start (ap, fmt);    /*lint !e718 !e746 */
  601.         (void) vprintf (fmt, ap);
  602.         va_end (ap);
  603.         (void) fflush (stdout);
  604.     }
  605.     if (LogInFile) {
  606.         if ((fp = fopen (bootplog, "a+")) == NULL) {
  607.             tputs ("Cannot open bootplog.\n");
  608.             return;
  609.         }
  610.         va_start (ap, fmt);
  611.         (void) vfprintf (fp, fmt, ap);
  612.         va_end (ap);
  613.         (void) fflush (fp);
  614.         (void) fclose (fp);
  615.     }
  616. }
  617.  
  618. #endif    /* BOOTPSERVER */
  619.